package com.example.cd5160866.urlapp.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;

import com.example.cd5160866.urlapp.R;

public class ShadowView extends ViewGroup {

    private static final String TAG = ShadowView.class.getSimpleName();

    private final Paint mShadowPaint;

    private float cornerRadius;

    private float shadowSizeStart;

    private float shadowSizeEnd;

    private float shadowSizeTop;

    private float shadowSizeBottom;

    private int mDefaultColor;

    private int mPressColor;

    private boolean isClicked;

    /**
     * 指定一个view的类名和 属性直接生成带阴影的view
     */
    public static ShadowView generateAnShadowView(Context context, AttributeSet viewAttrs, @Nullable Class<? extends View> viewClass) {
        ShadowView shadowView = new ShadowView(context);
        View view;
        ViewGroup.LayoutParams params = shadowView.generateLayoutParams(viewAttrs);
        try {
            view = viewClass.getConstructor(Context.class, AttributeSet.class).newInstance(context, viewAttrs);
        } catch (Exception e) {
            view = new View(context, viewAttrs);
            e.printStackTrace();
        }
        shadowView.addView(view, params);
        return shadowView;
    }


    /**
     * 指定一个view的类名和 属性直接生成带阴影的view
     */
    public static ShadowView replaceOriginWithShadowView(Context context, AttributeSet viewAttrs, @Nullable Class<? extends View> viewClass) {
        ShadowView shadowView = new ShadowView(context);
        View view;
        LayoutParams params = (LayoutParams) shadowView.generateLayoutParams(viewAttrs);
        params.setMargins(0, 0, 0, 0);
        if (params.width == 0) {
            params.width = ViewGroup.LayoutParams.MATCH_PARENT;
        }
        if (params.height == 0) {
            params.height = ViewGroup.LayoutParams.MATCH_PARENT;
        }
        try {
            view = viewClass.getConstructor(Context.class, AttributeSet.class).newInstance(context, viewAttrs);
        } catch (Exception e) {
            view = new View(context, viewAttrs);
            e.printStackTrace();
        }
        shadowView.addView(view, params);
        return shadowView;
    }


    public ShadowView(Context context) {
        this(context, null);
    }

    public ShadowView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ShadowView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ShadowView);
        mDefaultColor = a.getColor(R.styleable.ShadowView_ShadowDefaultColor, Color.TRANSPARENT);
        mPressColor = a.getColor(R.styleable.ShadowView_ShadowPressedColor, Color.TRANSPARENT);
        shadowSizeStart = a.getDimensionPixelOffset(R.styleable.ShadowView_ShadowSizeStart, 0);
        shadowSizeEnd = a.getDimensionPixelOffset(R.styleable.ShadowView_ShadowSizeEnd, 0);
        shadowSizeTop = a.getDimensionPixelOffset(R.styleable.ShadowView_ShadowSizeTop, 0);
        shadowSizeBottom = a.getDimensionPixelOffset(R.styleable.ShadowView_ShadowSizeBottom, 0);
        cornerRadius = a.getDimensionPixelOffset(R.styleable.ShadowView_ShadowCornerRadius, 0);
        a.recycle();
        mShadowPaint = new Paint();
        mShadowPaint.setStyle(Paint.Style.FILL);
        mShadowPaint.setAntiAlias(true);
        mShadowPaint.setColor(mDefaultColor);
        setPaintShadowRadius(mShadowPaint, shadowSizeStart);
        setLayerType(LAYER_TYPE_SOFTWARE, null);
    }

    public void setShadowSize(int left, int top, int right, int bottom) {
        if (left == this.shadowSizeStart && top == this.shadowSizeTop && right == this.shadowSizeEnd && bottom == this.shadowSizeBottom) {
            return;
        }
        this.shadowSizeStart = left;
        this.shadowSizeEnd = right;
        this.shadowSizeTop = top;
        this.shadowSizeBottom = bottom;
        requestLayout();
    }

    public void setStatusColors(int defaultColor, int pressColor) {
        this.mDefaultColor = defaultColor;
        this.mPressColor = pressColor;
        updateShadowColor(mDefaultColor);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        boolean dispatch = super.dispatchTouchEvent(ev);
        if (dispatch) {
            switch (ev.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    updatePressStatus(true);
                    break;
                case MotionEvent.ACTION_UP:
                    updatePressStatus(false);
                    break;
                default:
                    break;
            }
        }
        return dispatch;
    }

    private void updatePressStatus(boolean isClick) {
        if (mPressColor == 0 || mDefaultColor == 0) {
            return;
        }
        if (isClicked == isClick) {
            return;
        }
        isClicked = isClick;
        updateShadowColor(isClick ? mPressColor : mDefaultColor);
    }

    private void updateShadowColor(int color) {
        mShadowPaint.setColor(color);
        setPaintShadowRadius(mShadowPaint, shadowSizeStart);
    }

    private void setPaintShadowRadius(Paint paint, float radius) {
        if (radius <= 0 || paint == null) {
            return;
        }
        paint.setMaskFilter(new BlurMaskFilter(radius, BlurMaskFilter.Blur.NORMAL));
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        Log.d(TAG, "dispatchDraw");
        View child = getChildAt(0);
        int left = child.getLeft();
        int top = child.getTop();
        int right = child.getRight();
        int bottom = child.getBottom();
        Path drawablePath = new Path();
        drawablePath.moveTo(left + cornerRadius, top);
        drawablePath.arcTo(new RectF(left, top, left + 2 * cornerRadius, top + 2 * cornerRadius), -90, -90, false);
        drawablePath.lineTo(left, bottom - cornerRadius);
        drawablePath.arcTo(new RectF(left, bottom - 2 * cornerRadius, left + 2 * cornerRadius, bottom), 180, -90, false);
        drawablePath.lineTo(right - cornerRadius, bottom);
        drawablePath.arcTo(new RectF(right - 2 * cornerRadius, bottom - 2 * cornerRadius, right, bottom), 90, -90, false);
        drawablePath.lineTo(right, top - cornerRadius);
        drawablePath.arcTo(new RectF(right - 2 * cornerRadius, top, right, top + 2 * cornerRadius), 0, -90, false);
        drawablePath.close();
        canvas.drawPath(drawablePath, mShadowPaint);
        super.dispatchDraw(canvas);
//        if (child.getVisibility() != getVisibility()) {
//            setVisibility(child.getVisibility());
//        }
    }

//    @Override
//    public void addView(View child, int index, ViewGroup.LayoutParams params) {
//        super.addView(child, index, params);
//        child.setOnSystemUiVisibilityChangeListener(new OnSystemUiVisibilityChangeListener() {
//            @Override
//            public void onSystemUiVisibilityChange(int visibility) {
//                Log.d(TAG, "child visibility: "+visibility);
//                setVisibility(visibility);
//            }
//        });
//        child.set
//    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        Log.d(TAG, "onMeasure");
        int height;
        int width;
        int widthMeasureSpecSize;
        int heightMeasureSpecSize;
        View child = getChildAt(0);
        LayoutParams childLayoutParams = (LayoutParams) child.getLayoutParams();
        if (childLayoutParams.width == LayoutParams.MATCH_PARENT) {
            widthMeasureSpecSize = (MeasureSpec.getSize(widthMeasureSpec) - (int) (shadowSizeStart + shadowSizeEnd));
            widthMeasureSpec = MeasureSpec.makeMeasureSpec(widthMeasureSpecSize, MeasureSpec.EXACTLY);
        }
        if (childLayoutParams.height == LayoutParams.MATCH_PARENT) {
            heightMeasureSpecSize = (MeasureSpec.getSize(heightMeasureSpec) - (int) (shadowSizeBottom + shadowSizeTop));
            heightMeasureSpec = MeasureSpec.makeMeasureSpec(heightMeasureSpecSize, MeasureSpec.EXACTLY);
        }
        measureChild(child, widthMeasureSpec, heightMeasureSpec);
        int childHeight = child.getMeasuredHeight();
        int childWidth = child.getMeasuredWidth();
        width = (int) (childWidth + shadowSizeStart + shadowSizeEnd);
        height = (int) (childHeight + shadowSizeTop + shadowSizeBottom);
        setMeasuredDimension(width, height);
    }

    public static class LayoutParams extends MarginLayoutParams {

        public LayoutParams(Context c, AttributeSet attrs) {
            super(c, attrs);
        }

        public LayoutParams(int width, int height) {
            super(width, height);
        }

        public LayoutParams(ViewGroup.LayoutParams source) {
            super(source);
        }
    }

    @Override
    protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
        return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
    }

    @Override
    protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
        return new LayoutParams(p);
    }

    @Override
    public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new LayoutParams(getContext(), attrs);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        Log.d(TAG, "onLayout");
        View child = getChildAt(0);
        int childMeasureWidth = child.getMeasuredWidth();
        int childMeasureHeight = child.getMeasuredHeight();
        child.layout((int) shadowSizeStart, (int) shadowSizeTop, (int) (shadowSizeStart + childMeasureWidth), (int) (shadowSizeTop + childMeasureHeight));
    }
}

